package service

import (
	"fmt"
	"io"
	"net/http"
	"one-api/common"
	"one-api/model"
	"one-api/types"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

// APIForwardService API转发服务
type APIForwardService struct{}

// ForwardRequest 转发请求到第三方API
func (s *APIForwardService) ForwardRequest(c *gin.Context, apiPath string) *types.NewAPIError {
	// 1. 获取转发配置
	config, err := model.GetForwardConfigByPath(apiPath)
	if err != nil {
		common.LogError(c, fmt.Sprintf("failed to get forward config for path %s: %v", apiPath, err))
		return types.NewErrorWithStatusCode(fmt.Errorf("failed to get forward config"), types.ErrorCodeQueryDataError, 500)
	}

	// 2. 可选的用户信息（如果存在则进行扣费与日志记录）
	userId := c.GetInt("id")
	var costQuota int
	if userId != 0 {
		// 3. 检查用户余额
		user, uerr := model.GetUserById(userId, false)
		if uerr != nil {
			common.LogError(c, fmt.Sprintf("failed to get user %d: %v", userId, uerr))
			return types.NewErrorWithStatusCode(fmt.Errorf("failed to get user"), types.ErrorCodeQueryDataError, 500)
		}
		// 将USD价格转换为quota（严格使用配置金额，不参与倍率）
		costQuota = int(config.Cost * common.QuotaPerUnit)
		if user.Quota < costQuota {
			return types.NewErrorWithStatusCode(fmt.Errorf("insufficient quota"), types.ErrorCodeInsufficientUserQuota, 400)
		}
	}

	// 4. 计算目标URL（若绑定了转发渠道，则按 base_url + apiPath 拼接，并保留原请求的查询串）
	target := strings.TrimSpace(config.TargetURL)
	var upstreamAPIKey string
	if config.ChannelID > 0 {
		ch, chErr := model.GetChannelById(int(config.ChannelID), true)
		if chErr != nil {
			common.LogError(c, fmt.Sprintf("failed to get channel %d: %v", config.ChannelID, chErr))
			return types.NewErrorWithStatusCode(fmt.Errorf("failed to get forward channel"), types.ErrorCodeQueryDataError, 500)
		}
		base := strings.TrimRight(ch.GetBaseURL(), "/")
		full := base + apiPath
		if q := c.Request.URL.RawQuery; q != "" {
			full = full + "?" + q
		}
		target = full
		// 需求2：将对应渠道的 API-KEY 透传到上游
		upstreamAPIKey = strings.TrimSpace(ch.Key)
	}

	// 5. 转发请求
	startTime := time.Now()
	response, err := s.doForwardRequest(c, target, upstreamAPIKey)
	useTimeSeconds := int(time.Since(startTime).Seconds())

	if err != nil {
		common.LogError(c, fmt.Sprintf("forward request failed: %v", err))
		// 转发失败不扣费，直接返回错误
		return types.NewErrorWithStatusCode(fmt.Errorf("forward request failed"), types.ErrorCodeDoRequestFailed, 502)
	}

	// 6. 转发成功，若存在用户则扣除费用并记录日志
	if userId != 0 && costQuota > 0 {
		if rerr := s.recordConsumption(c, userId, config, useTimeSeconds, apiPath, costQuota); rerr != nil {
			common.LogError(c, fmt.Sprintf("failed to record consumption: %v", rerr))
			// 即使记录失败，也要返回响应给用户
		}
	}

	// 7. 将第三方API的响应返回给用户
	s.forwardResponse(c, response)
	return nil
}

// doForwardRequest 执行实际的转发请求
func (s *APIForwardService) doForwardRequest(c *gin.Context, targetURL string, upstreamAPIKey string) (*http.Response, error) {
	// 创建HTTP客户端
	client := &http.Client{
		Timeout: 60 * time.Second,
	}

	// 构建请求
	req, err := http.NewRequest(c.Request.Method, targetURL, c.Request.Body)
	if err != nil {
		return nil, err
	}

	// 复制请求头
	for key, values := range c.Request.Header {
		// 跳过一些不应该转发的头部
		if key == "Host" || key == "Content-Length" {
			continue
		}
		for _, value := range values {
			req.Header.Add(key, value)
		}
	}

	// 设置上游鉴权：优先使用渠道 key 作为 Bearer
	if upstreamAPIKey != "" {
		// 如果已有 Authorization，覆盖为上游渠道的 key
		req.Header.Set("Authorization", "Bearer "+upstreamAPIKey)
	}

	// 设置新的Host
	req.Host = ""

	// 执行请求
	return client.Do(req)
}

// forwardResponse 将第三方API的响应转发给用户
func (s *APIForwardService) forwardResponse(c *gin.Context, response *http.Response) {
	defer response.Body.Close()

	// 复制响应头
	for key, values := range response.Header {
		for _, value := range values {
			c.Header(key, value)
		}
	}

	// 设置状态码
	c.Status(response.StatusCode)

	// 复制响应体
	body, err := io.ReadAll(response.Body)
	if err != nil {
		common.LogError(c, fmt.Sprintf("failed to read response body: %v", err))
		c.String(500, "Failed to read response")
		return
	}

	c.Data(response.StatusCode, response.Header.Get("Content-Type"), body)
}

// recordConsumption 记录消费日志和扣除费用
func (s *APIForwardService) recordConsumption(c *gin.Context, userId int, config *model.APIForwardConfig, useTimeSeconds int, apiPath string, costQuota int) error {
	// 1. 扣除用户余额（严格使用传入的costQuota）
	err := model.DecreaseUserQuota(userId, costQuota)
	if err != nil {
		return fmt.Errorf("failed to decrease user quota: %v", err)
	}

	// 2. 记录消费日志
	modelName := config.ModelName
	if strings.TrimSpace(modelName) == "" {
		modelName = fmt.Sprintf("forward:%s", apiPath)
	}
	group := c.GetString("group")
	if group == "" {
		if userCache, e := model.GetUserCache(userId); e == nil {
			group = userCache.Group
		}
	}
	params := model.RecordConsumeLogParams{
		ChannelId:        int(config.ChannelID),
		PromptTokens:     0, // 转发API没有token计数
		CompletionTokens: 0,
		ModelName:        modelName,
		TokenName:        c.GetString("token_name"),
		Quota:            costQuota,
		Content:          fmt.Sprintf("forward:%s", apiPath),
		TokenId:          c.GetInt("token_id"),
		UserQuota:        0, // 这个字段在RecordConsumeLog中会被忽略
		UseTimeSeconds:   useTimeSeconds,
		IsStream:         false,
		Group:            group,
		Other: map[string]interface{}{
			"forward_type": "api_forward",
			"target_url":   config.TargetURL,
			"api_path":     apiPath,
			"cost":         config.Cost,
		},
	}

	model.RecordConsumeLog(c, userId, params)
	return nil
}

// GetForwardConfigs 获取所有转发配置
func (s *APIForwardService) GetForwardConfigs(page, pageSize int) ([]*model.APIForwardConfig, int64, error) {
	return model.GetAllForwardConfigs(page, pageSize)
}

// CreateForwardConfig 创建转发配置
func (s *APIForwardService) CreateForwardConfig(config *model.APIForwardConfig) error {
	return model.CreateForwardConfig(config)
}

// UpdateForwardConfig 更新转发配置
func (s *APIForwardService) UpdateForwardConfig(config *model.APIForwardConfig) error {
	return model.UpdateForwardConfig(config)
}

// DeleteForwardConfig 删除转发配置
func (s *APIForwardService) DeleteForwardConfig(id uint) error {
	return model.DeleteForwardConfig(id)
}
